home *** CD-ROM | disk | FTP | other *** search
- #include "kerbind.h"
- #include "gs_descr.h"
-
- static long gssock_open(FILEPTR *fp);
- static long gssock_write(FILEPTR *fp, char *buf, long buflen);
- #if 0 /* This is not static anymore, so that gs_read_delim() can use it */
- static
- #endif
- long gssock_read(FILEPTR *fp, char *buf, long buflen);
- static long gssock_lseek(FILEPTR *fp, long where, short whence);
- static long gssock_ioctl(FILEPTR *fp, short cmd, void *buf);
- static long gssock_datime(FILEPTR *fp, short *timeptr, short rwflag);
- static long gssock_close(FILEPTR *fp, short pid);
- static long gssock_select(FILEPTR *fp, long proc, short mode);
- static void gssock_unselect(FILEPTR *fp, long proc, short mode);
- static long gs_command(FILEPTR *fp, union GS_cmd *args);
-
- struct devdrv gsdev = {
- gssock_open, gssock_write, gssock_read, gssock_lseek,
- gssock_ioctl, gssock_datime, gssock_close,
- gssock_select, gssock_unselect,
- { 0L, 0L, 0L }
- };
-
- struct dev_descr gsdev_descr = {
- &gsdev, 0, 0, (struct tty *)0, { 0L, 0L, 0L, 0L }
- };
-
- static long gssock_open(FILEPTR *fp)
- {
- struct GS *gs = gs_create();
-
- if (!gs) {
- DEBUG(("gsdev: gssock_open: out of memory"));
- LOG(DBG_ERROR, "gssock_open() returns %E", E_NOMEM);
- return E_NOMEM;
- }
-
- LOG(DBG_SYSCALL, "gssock_open() returns 0");
- fp->devinfo = (long)gs;
- return 0;
- }
-
- static long gssock_write(FILEPTR *fp, char *buf, long buflen)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
- long r, n;
-
- LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l)",
- (void *)fp, (void *)buf, buflen);
-
- if (gs->flags & GS_NOSOCKET) {
- LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): bad handle",
- (void *)fp, (void *)buf, buflen);
- return E_BADHANDLE;
- }
-
- if ((gs->flags & GS_LISTENING) && gs_accept(gs) != 0) {
- LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l): no connections arrived",
- (void *)fp, (void *)buf, buflen);
- return E_LISTEN;
- }
-
- #if 0
- /* This is kind of a lie, but at least it's an error code a STiK app will
- * be prepared to deal with. */
- if ((gs->flags & GS_PEND_OPEN) && gs_establish(gs) != 0) {
- LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l): open in progress",
- (void *)fp, (void *)buf, buflen);
- return E_OBUFFULL;
- }
- #endif
-
- /* STiK has no provisions for writing part of a buffer and saving the
- * rest for later; so make sure we can write the whole thing. */
- r = f_cntl(gs->sock_fd, (long)&n, FIONWRITE);
- if (r < 0) {
- LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): Fcntl(FIONWRITE) returned %d",
- (void *)fp, (void *)buf, buflen, r);
- return gs_xlate_error(r, "gssock_write");
- }
- if (n < buflen) {
- LOG(DBG_ERROR,
- "In gssock_write(%p, %p, %l): can only write %l bytes; "
- "returning E_OBUFFULL",
- (void *)fp, (void *)buf, buflen, n);
- return E_OBUFFULL;
- }
-
- /* Okay, we can safely write. */
- r = f_write(gs->sock_fd, buflen, buf);
- if (r < 0) {
- LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): Fwrite() returned %e",
- (void *)fp, (void *)buf, buflen, r);
- return gs_xlate_error(r, "gssock_write");
- } else {
- /* Okay, according to the Fcntl(), we should have been able to write
- * everything; warn if we didn't. */
- if (r < buflen)
- LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): "
- "only got %l of %l bytes",
- (void *)fp, (void *)buf, buflen, r, buflen);
- LOG(DBG_SYSCALL, "gssock_write(%p, %p, %l) returns E_NORMAL",
- (void *)fp, (void *)buf, buflen);
- return E_NORMAL;
- }
- }
-
- long gssock_read(FILEPTR *fp, char *buf, long buflen)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
- long r, n;
-
- LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l)",
- (void *)fp, (void *)buf, buflen);
-
- if (gs->flags & GS_NOSOCKET) {
- LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): bad handle",
- (void *)fp, (void *)buf, buflen);
- return E_BADHANDLE;
- }
-
- if ((gs->flags & GS_LISTENING) && gs_accept(gs) != 0) {
- LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): no connections arrived",
- (void *)fp, (void *)buf, buflen);
- return E_LISTEN;
- }
-
- #if 0
- if ((gs->flags & GS_PEND_OPEN) && gs_establish(gs) != 0) {
- LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): open in progress",
- (void *)fp, (void *)buf, buflen);
- return E_NODATA;
- }
- #endif
-
- /* STiK has no provisions for reading less than a full buffer's worth of
- * data; make sure we can fill the buffer. */
- n = gs_canread(fp);
- if (n < 0)
- return n;
- if (n < buflen) {
- LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): only %l bytes available",
- (void *)fp, (void *)buf, buflen, n);
- return E_NODATA;
- }
-
- /* Okay, we can safely read. */
- r = f_read(gs->sock_fd, buflen, buf);
- if (r < 0) {
- LOG(DBG_ERROR, "In gssock_read(%p, %p, %l): Fread() returns %e",
- (void *)fp, (void *)buf, buflen, r);
- return gs_xlate_error(r, "gssock_read");
- } else {
- /* Okay, according to the Fcntl(), we should have been able to fill the
- * entire buffer; warn if we didn't. */
- if (r < buflen)
- LOG(DBG_ERROR, "In gssock_read(%p, %p, %l): "
- "only able to read %l of %l bytes",
- (void *)fp, (void *)buf, buflen, r, buflen);
- LOG(DBG_SYSCALL, "gssock_read(%p, %p, %l) reads %l bytes",
- (void *)fp, (void *)buf, buflen, r);
- return buflen;
- }
- }
-
- static long gssock_lseek(FILEPTR *fp, long where, short whence)
- {
- /* MiNTnet sockets don't allow this, and STiK has no provisions for it;
- * what're ya gonna do? ;) */
- return E_NOROUTINE;
- }
-
- static long gssock_ioctl(FILEPTR *fp, short cmd, void *buf)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
-
- switch (cmd) {
- /* Most commands have args, and so get called via GLUESTIK_CMD. */
- case GLUESTIK_CMD:
- return gs_command(fp, (union GS_cmd *)buf);
-
- /* These commands have no args (or a simple arg passed via |buf|), and
- * so can also be called directly. */
- case CNBYTECOUNT_CMD:
- return gs_canread(fp);
- case CNGETNDB_CMD:
- return gs_readndb(fp);
- case CNGETINFO_CMD:
- LOG(DBG_SYSCALL, "In gssock_ioctl(%p, CNGETINFO_CMD)", (void *)fp);
- if (!gs) {
- LOG(DBG_ERROR, "In gssock_ioctl(%p, CNGETINFO_CMD): bad handle",
- (void *)fp);
- return E_BADHANDLE;
- }
- LOG(DBG_SYSCALL, "gssock_ioctl(%p, CNGETINFO_CMD) returns %p",
- (void *)fp, (void *)&(gs->cib));
- return (long)&(gs->cib);
- case GETERRTXT_CMD:
- return (long)do_get_err_text((int16)(long)buf);
- case GETDBGLVL_CMD:
- return debug_level;
- case SETDBGLVL_CMD:
- debug_level = (long)buf;
- return 0;
-
- /* Everything else gets passed through to the underlying socket. */
- default:
- if (gs->flags & GS_NOSOCKET) {
- LOG(DBG_ERROR, "In gssock_ioctl(%p): bad handle", (void *)fp);
- return E_BADHANDLE;
- }
- return f_cntl(gs->sock_fd, buf, cmd);
- }
- }
-
- static long gssock_datime(FILEPTR *fp, short *timeptr, short rwflag)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
-
- if (gs->flags & GS_NOSOCKET) {
- LOG(DBG_ERROR, "In gssock_datime(%p, %p, %d): bad handle",
- (void *)fp, (void *)timeptr, (int)rwflag);
- return E_BADHANDLE;
- }
-
- return f_datime(timeptr, gs->sock_fd, rwflag);
- }
-
- static long gssock_close(FILEPTR *fp, short pid)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
-
- LOG(DBG_SYSCALL, "In gssock_close(%p)", (void *)fp);
- gs_release(gs);
- return 0;
- }
-
- /* Fselect() should never be called on a GlueSTiK connection directly, but
- * on the contained socket via TCP_wait_state() or similar. */
- static long gssock_select(FILEPTR *fp, long proc, short mode)
- {
- return E_NOROUTINE;
- }
-
- static void gssock_unselect(FILEPTR *fp, long proc, short mode)
- {
- return;
- }
-
- static long gs_command(FILEPTR *fp, union GS_cmd *args)
- {
- struct GS *gs = (struct GS *)fp->devinfo;
-
- switch (args->cmd.cmd) {
- case KRMALLOC_CMD:
- return (long)gs_mem_alloc(args->KRmalloc_cmd.size);
- case KRFREE_CMD:
- gs_mem_free(args->KRfree_cmd.mem);
- return 0;
- case KRGETFREE_CMD:
- return gs_mem_getfree(args->KRgetfree_cmd.flag);
- case KRREALLOC_CMD:
- return (long)gs_mem_realloc(args->KRrealloc_cmd.mem,
- args->KRrealloc_cmd.newsize);
- case GETVSTR_CMD:
- return (long)gs_getvstr(args->getvstr_cmd.var);
- case TCP_OPEN_CMD:
- return gs_connect(fp, args);
- case TCP_WAIT_CMD:
- return gs_wait(fp, args->TCP_wait_state_cmd.timeout);
- case UDP_OPEN_CMD:
- return gs_udp_open(fp, args);
- case CNBYTECOUNT_CMD:
- return gs_canread(fp);
- case CNGETNDB_CMD:
- return gs_readndb(fp);
- case CNGETINFO_CMD:
- if (!gs)
- return E_BADHANDLE;
- return (long)&(gs->cib);
- case SETVSTR_CMD:
- return gs_setvstr(args->setvstr_cmd.vs, args->setvstr_cmd.value);
- case CNGETS_CMD:
- return gs_read_delim(fp, args);
- case GETERRTXT_CMD:
- return (long)do_get_err_text(args->get_err_text_cmd.err);
- case LOGENTRY_CMD:
- if (args->log_entry_cmd.lev <= debug_level)
- log_entry_raw(args->log_entry_cmd.pid, args->log_entry_cmd.lev,
- args->log_entry_cmd.line);
- return 0;
- case GETDBGLVL_CMD:
- return debug_level;
- case SETDBGLVL_CMD:
- debug_level = args->set_dbglvl_cmd.lev;
- return 0;
- default:
- return E_PARAMETER;
- }
- }